  /*
   * Copyright 2012 The Netty Project
   *
   * The Netty Project licenses this file to you under the Apache License,
   * version 2.0 (the "License"); you may not use this file except in compliance
   * with the License. You may obtain a copy of the License at:
   *
   *   https://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   * License for the specific language governing permissions and limitations
   * under the License.
   */
  package com.rs.caht.netty.websocket.officialdemo;

  import io.netty.channel.ChannelHandlerContext;
  import io.netty.channel.SimpleChannelInboundHandler;
  import io.netty.handler.codec.http.websocketx.*;

  import java.util.Locale;

  /**
   * Echoes uppercase content of text frames.
   */
  public class WebSocketFrameHandler extends SimpleChannelInboundHandler<WebSocketFrame> {
      private WebSocketServerHandshaker handshaker;
//  (1) 第一次握手由HTTP协议承载，所以是一个HTTP消息，根据消息头中是否包含"Upgrade"字段来判断是否是websocket。
//  (2) 通过校验后，构造WebSocketServerHandshaker，通过它构造握手响应信息返回给客户端，
//  同时将WebSocket相关的编码和解码类动态添加到ChannelPipeline中。下面分析链路建立之后的操作：
//  (1) 客户端通过文本框提交请求给服务端，Handler收到之后已经解码之后的WebSocketFrame消息。
//  (2) 如果是关闭按链路的指令就关闭链路
//  (3) 如果是维持链路的ping消息就返回Pong消息。
//  (4) 否则就返回应答消息
      @Override
      protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception {
          // ping and pong frames already handled
          // 判断是否是关闭链路的指令
          if (frame instanceof CloseWebSocketFrame) {
              handshaker.close(ctx.channel(),
                      (CloseWebSocketFrame) frame.retain());
              System.out.println("cloase 命令");
              return;
          }
          // 判断是否是Ping消息
          if (frame instanceof PingWebSocketFrame) {
              System.out.println("Ping消息");
              ctx.channel().write(
                      new PongWebSocketFrame(frame.content().retain()));
              return;
          }

          if (frame instanceof TextWebSocketFrame) {
              // Send the uppercase string back.
              String request = ((TextWebSocketFrame) frame).text();
              ctx.channel().writeAndFlush(new TextWebSocketFrame(request.toUpperCase(Locale.US)));
          } else {
              String message = "unsupported frame type: " + frame.getClass().getName();
              throw new UnsupportedOperationException(message);
          }
      }
  }